package de.rj.urwalking.ui.fragments;

import java.util.ArrayList;

import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;

import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;

import de.rj.urwalking.R;
import de.rj.urwalking.config.Config;
import de.rj.urwalking.config.Constants;
import de.rj.urwalking.db.DBSalientObject;
import de.rj.urwalking.loader.IndoorSalientObjectLoader;
import de.rj.urwalking.ui.IndoorRenderer;
import de.rj.urwalking.ui.fragments.dialog.IndoorObjectDialogFragment;
import de.rj.urwalking.util.PrefUtil;
import de.rose_mobil.models.route.Route;

public class IndoorFragment extends JpctFragment {

	private IndoorRenderer renderer;
	protected Object3D currentlySelectedObject;
	private SalientObjectLoaderCallbacks salientObjectLoaderCallbacks;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		View rootView = inflater.inflate(R.layout.fragment_indoor, container, false);
		initUI(rootView);
		init3D();
		startLoader();

		return rootView;
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		outState.putSerializable("cameraVectors", renderer.getCameraVectors());
		outState.putFloat("fov", renderer.getFov());
		if (Config.DEBUG) Log.d(Config.TAG, "saving fov: " + renderer.getFov());
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);

		if (savedInstanceState == null) return;

		SimpleVector[] cameraVectors = (SimpleVector[]) savedInstanceState.getSerializable("cameraVectors");
		renderer.setCameraVectors(cameraVectors);
		renderer.setCameraFov(savedInstanceState.getFloat("fov"));
		if (Config.DEBUG) Log.d(Config.TAG, "restored fov: " + savedInstanceState.getFloat("fov"));
	}

	private void init3D() {
		super.renderer = new IndoorRenderer(getActivity());
		renderer = (IndoorRenderer) super.renderer;
		mGLView.setRenderer(renderer);

	}


	public void checkPreferences() {
		if (PrefUtil.readBoolean(getString(R.string.key_pref_show_landmarks), getActivity(), false)) {
			renderer.showLandmarks();
		} else {
			renderer.hideLandmarks();
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (v.getId()) {

		case R.id.buttonLeft:
			return handleButtonLeft(event);
		case R.id.buttonRight:
			return handleButtonRight(event);
		case R.id.buttonForward:
			return handleButtonForward(event);
		case R.id.buttonBackward:
			return handleButtonBackward(event);
		case R.id.surfaceView:
			return handleSurfaceTouch(event);
		}

		return false;
	}

	private boolean handleSurfaceTouch(MotionEvent event) {
		boolean gestureDetected = gestureDetector.onTouchEvent(event);
		scaleGestureDetector.onTouchEvent(event);

		if (!scaleGestureDetector.isInProgress()) {
			boolean hasTurned = renderer.adjustEgoPerspective(event);

			if (hasTurned && mActivity.getUseCompass()) {
				mActivity.disableCompassMovement(true);
			}
		}

		return gestureDetected;
	}

	private void startLoader() {

		LoaderManager.enableDebugLogging(Config.DEBUG);

		salientObjectLoaderCallbacks = new SalientObjectLoaderCallbacks();

		LoaderManager lm = getActivity().getSupportLoaderManager();
		lm.initLoader(Constants.SALIENT_OBJECT_LOADER_ID, null, salientObjectLoaderCallbacks);

	}

	private class SalientObjectLoaderCallbacks implements LoaderCallbacks<ArrayList<DBSalientObject>> {

		public Loader<ArrayList<DBSalientObject>> onCreateLoader(int id, Bundle args) {
			return new IndoorSalientObjectLoader(getActivity());
		}

		public void onLoadFinished(Loader<ArrayList<DBSalientObject>> loader, ArrayList<DBSalientObject> data) {
			renderer.setSalientObjects(data);
			mLoaderProgressBar.setVisibility(View.INVISIBLE);
			
		}

		public void onLoaderReset(Loader<ArrayList<DBSalientObject>> loader) {
		}

	}

	private void showObjectDialog(Object3D object3d) {
		IndoorObjectDialogFragment dialogFragment = new IndoorObjectDialogFragment();

		Bundle args = new Bundle();
		args.putSerializable("object", object3d);
		args.putSerializable("projectionMatrix", renderer.getProjectionMatrix());
		args.putDouble("currentLatitude", renderer.getCameraPosition().y);
		args.putDouble("currentLongitude", renderer.getCameraPosition().x);

		dialogFragment.setArguments(args);

		FragmentManager fm = getChildFragmentManager();
		dialogFragment.show(fm, "fragment_object_dialog");

	}

	@Override
	public void setLocation(Location location) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setOrientation(float orientation) {

		renderer.setCameraAngle(orientation);
		renderer.updateUserArrow(orientation);
		mCompassView.updateDirection(orientation);

	}

	public void stepForward(float length) {
		renderer.stepForward(length);
	}

	@Override
	public void setRoute(Route route) {
		// TODO Auto-generated method stub

	}

	

	@Override
	public void onScaleEnd(ScaleGestureDetector detector) {
	}

	@Override
	public boolean onScaleBegin(ScaleGestureDetector detector) {
		return true;
	}

	@Override
	public boolean onScale(ScaleGestureDetector detector) {
		float scaleFactor = detector.getScaleFactor();

		renderer.zoomInEgoPerspective(scaleFactor);

		return true;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		return true;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {

		Object3D pickedObject = renderer.checkRayCollision(e.getX(), e.getY());

		if (pickedObject == null) {
			return false;
		} else {
			currentlySelectedObject = pickedObject;
			showObjectDialog(pickedObject);
			return true;
		}

	}

	@Override
	public void onLongPress(MotionEvent e) {
		Object3D pickedObject = renderer.checkRayCollision(e.getX(), e.getY());

		if (pickedObject == null) return;

		currentlySelectedObject = pickedObject;
		showObjectDialog(pickedObject);
	}

	@Override
	public void setObjectName(String name) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onWorldReady() {
		// TODO Auto-generated method stub
		
	}
}
